package com.luo.demo.oidc.combo.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;

/**
 * SpringSecurity OAuth2 Resource Server配置
 *
 * @author luohq
 * @version 1.0.0
 * @date 2022-02-21 10:14
 */
@Configuration
public class ResourceApiSecurityConfig {

    /**
     * 需要进行OAuth2 Resource验证的API模式列表
     */
    @Value("${spring.security.oauth2.resourceserver.api-path-mvc-patterns}")
    private String[] apiPathMvcPatterns;

    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE + 1) //在AuthServer后，在Form验证前
    SecurityFilterChain rabcApiSecurityFilterChain(HttpSecurity http, ResourceApiAuthorizationManager resourceApiAuthorizationManager) throws Exception {
        http
                //设置request matcher(仅针对需要进行OAuth Resource验证的API进行拦截)
                .requestMatchers(requestMatchers -> requestMatchers
                        .mvcMatchers(this.apiPathMvcPatterns)
                )
                //禁用csrf防御（避免post请求被拦截）
                .csrf().disable()
                //session管理
                .sessionManagement(session -> session
                        //无状态session（即不使用session，避免创建session 及 使用session存储Authentication信息进而绕过验证）
                        .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                )
                //授权设置
                .authorizeHttpRequests(authorize -> authorize
                        //集成自定义验证器
                        .anyRequest().access(resourceApiAuthorizationManager)
                )
                //启用JWT验证
                .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
        return http.build();
    }
}
